<script setup>
import {ref, watch} from "vue";
import {CirclePlus, RemoveFilled, UploadFilled} from "@element-plus/icons-vue";
import {ElMessage, ElMessageBox} from "element-plus";
import {importAchievement} from "@/api/achievement";
import {getUsernameById} from "@/api/user";
import {SUCCESS} from "@/core/constants/HttpStatus";
import {useRouter} from "vue-router";
// 防抖
const debounce = (func, onlyAdvisor = false) => {
  let timer = null;
  return function (...args) {
    if (timer) {
      clearTimeout(timer);
    }
    timer = setTimeout(() => (func && func(args, onlyAdvisor)), 800);
  }
}
// 自动获取姓名
const fetchName = async ([object, id], onlyAdvisor = false) => {
  console.log(id);
  if (!checkId(id, onlyAdvisor)) {
    return;
  }
  try {
    const res = await getUsernameById(id);
    const {code, data, msg} = res.data;
    if (code != SUCCESS) {
      throw new Error(msg);
    }
    object.name = data || "";
  } catch (e) {
    ElMessage.error(e?.message || "获取姓名异常")
  }
}

const typeNameList = ref(["竞赛", "软著", "专利", "论文", "项目",]);
const levelList = ref(["国际级", "国家级", "省级", "市级", "校级"]);
const infoFormRef = ref(null);
const infoForm = ref({
  title: "",
  possessors: [
    {id: "", name: "", queryHandler: debounce(fetchName)},
  ],
  advisor: {
    // 是否有指导老师
    have: 1,
    infos: [
      {id: "", name: "", queryHandler: debounce(fetchName, true)},
    ]
  },
  type: 0,
  level: "",
  achieveTime: "",
  description: "",
  fileList: [],
})
const checkId = (id, onlyAdvisor = false) => {
  // 只能是工号
  if (onlyAdvisor && id.length !== 8) {
    return false;
  }
  // 学号 | 工号
  if (id.length !== 12 && id.length !== 8) {
    return false;
  }
  // 都为数字
  let regExp = new RegExp("^\\d+$");
  if (!regExp.test(id)) {
    return false;
  }
  return true;
}
const validatePId = (rule, value, callback) => {
  if (checkId(value)) {
    callback()
  } else {
    callback(new Error("请输入正确的学号（工号）"))
  }
}
const validateAId = (rule, value, callback) => {
  if (checkId(value, true)) {
    callback()
  } else {
    callback(new Error("请输入正确的工号"))
  }
}
const validateTime = (rule, value, callback) => {
  if (checkTimeFormat(value)) {
    callback()
  } else {
    callback(new Error("请输入正确的日期格式"))
  }
}
const rules = {
  title: [{required: true, message: '请输入名称', trigger: 'blur'},],
  username: [{required: true, message: '请输入姓名', trigger: 'blur'}],
  possessorId: [
    {required: true, message: '请输入学号（工号）', trigger: 'blur'},
    {validator: validatePId, trigger: 'blur'}
  ],
  advisorId: [
    {required: true, message: '请输入工号', trigger: 'blur'},
    {validator: validateAId, trigger: 'blur'}
  ],
  type: [
    {required: true, message: '请选择所属类型', trigger: 'change'},
  ],
  level: [
    {required: true, message: '请选择实践成果等级', trigger: 'change'},
  ],
  achieveTime: [
    {required: true, message: '请输入获取时间', trigger: 'blur'},
    {validator: validateTime, trigger: 'blur'}
  ],
  description: [
    {required: true, message: '请输入实践成果简介', trigger: 'blur'},
  ],
}

const addPossessor = () => {
  let possessorItem = {
    id: "",
    name: "",
    queryHandler: debounce(fetchName)
  };
  infoForm.value.possessors.push(possessorItem);
}
const removePossessor = (idx) => {
  infoForm.value.possessors.splice(idx, 1);
}
/**
 * 指导老师相关逻辑
 */
watch(() => infoForm.value.advisor.have, (newValue, oldValue) => {
  console.log(newValue, oldValue);
  // 0：否，1：是
  if (newValue === 0) {
    // 移除原先指导老师
    infoForm.value.advisor.infos = [];
  } else {
    // 添加一位指导老师
    infoForm.value.advisor.infos.push({
      id: "",
      name: "",
      queryHandler: debounce(fetchName, true)
    });
  }
})
const addAdvisor = () => {
  let advisorItem = {
    id: "",
    name: "",
    queryHandler: debounce(fetchName, true)
  };
  infoForm.value.advisor.infos.push(advisorItem);
}
const removeAdvisor = (idx) => {
  infoForm.value.advisor.infos.splice(idx, 1);
}

let showFastInputDlg = ref(false);
let fastInputText = ref("");

const openFastInputDlg = () => {
  showFastInputDlg.value = true;
}
const trimLeftZero = str => str.replace(/^0+/, "");
const getDatetimeGroup = (timeStr) => {
  const timeReg = /^(\d{4})-(\d{2})-(\d{2})$/;
  //日期格式不匹配
  if (!timeReg.test(timeStr)) {
    return [];
  }
  const group = timeReg.exec(timeStr);
  //使用捕获组获取日期
  let year = Number(group[1]);
  let month = Number(trimLeftZero(group[2]));
  let day = Number(trimLeftZero(group[3]));
  return [year, month, day];
}
const checkTimeFormat = (timeStr) => {
  const datetimeGroup = getDatetimeGroup(timeStr);
  if (!datetimeGroup.length) {
    return false;
  }
  let [year, month, day] = datetimeGroup;
  const dateObj = new Date(year, month - 1, day);
  console.log(dateObj)
  if (year !== dateObj.getFullYear() || month !== dateObj.getMonth() + 1 || day !== dateObj.getDate()) {
    return false;
  }
  return true;
}
const handleFastInput = async () => {
  let text = fastInputText.value;
  // 多行只取一行
  let firstLine = text.split("\n")[0];
  console.log(firstLine)
  let [title, possessors, advisors, achieveTime] = firstLine.split(".");
  console.log(title, possessors, advisors, achieveTime)
  try {
    // 处理多位持有者和指导老师
    possessors = possessors
        .split(",")
        .map(item => {
          if (!checkId(item)) {
            throw new Error("请输入正确的学号（工号）")
          }
          return {id: item, name: "", queryHandler: debounce(fetchName)}
        });
    for (let item of possessors) {
      await fetchName([item, item.id]);
    }
    advisors = advisors
        .split(",")
        .map(item => {
          if (!checkId(item, true)) {
            throw new Error("请输入正确的工号")
          }
          return {id: item, name: "", queryHandler: debounce(fetchName, true)}
        });
    for (let item of advisors) {
      await fetchName([item, item.id]);
    }
    // achieveTime formatter check
    if (!checkTimeFormat(achieveTime)) {
      throw new Error("日期格式错误");
    }
  } catch (e) {
    ElMessage.warning(e?.message || "输入格式有误")
    return;
  }

  infoForm.value = {
    ...infoForm.value,
    title: title,
    possessors: possessors,
    advisor: {
      have: 1,
      infos: advisors
    },
    achieveTime
  }
  console.log(infoForm)
  showFastInputDlg.value = false;
  fastInputText.value = "";
}

// 上传图片
const uploaderRef = ref(null);
const FileLimitNum = 10;
const handleExceed = () => {
  ElMessage.warning(
      `仅支持上传${imgLimitNum}张图片！`
  );
};
// 图片上传检测
const httpRequest = (options) => (new Promise((resolve) => {
  infoForm.value.fileList.push(options.file);
  resolve(null);
}))
const handleBeforeUpload = (rawFile) => {
  const AllowImgTypes = ['application/pdf', 'image/jpg', 'image/jpeg', 'image/png'];
  console.log(rawFile.type);
  if (!AllowImgTypes.includes(rawFile.type)) {
    ElMessage.error('图片格式必须为 .PDF .JPG .JPEG .PNG！')
    return false
  }
  if (rawFile.size / 1024 / 1024 > 50) {
    ElMessage.error('图片大小不能超过50MB!')
    return false
  }
  return true
}
// 移除文件之前
const handleBeforeRemove = (uploadFile, uploadFiles) => {
  return ElMessageBox.confirm(
      `取消上传 ${uploadFile.name} ?`,
      {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
      }
  ).then(
      () => true,
      () => false
  );
};
// 移除
const handleRemove = (file) => {
  // console.log(file);
  const idx = infoForm.value.fileList.findIndex(item => item.uid === file.uid);
  console.log(idx);
  infoForm.value.fileList.splice(idx, 1);
}

const addAchievement = async () => {
  function transToDate(timeStr) {
    const [year, month, day] = getDatetimeGroup(timeStr);
    return new Date(year, month - 1, day);
  }
  const formData = new FormData();
  formData.append("title", infoForm.value.title);
  formData.append("possessorId", JSON.stringify(infoForm.value.possessors.map(item => item.id)));
  formData.append("possessorName", JSON.stringify(infoForm.value.possessors.map(item => item.name)));
  formData.append("advisorId", JSON.stringify(infoForm.value.advisor.infos.map(item => item.id)));
  formData.append("advisorName", JSON.stringify(infoForm.value.advisor.infos.map(item => item.name)));
  formData.append("teacherFlag", infoForm.value.advisor.have === 1);
  formData.append("type", infoForm.value.type);
  formData.append("level", infoForm.value.level);
  formData.append("achieveTime", infoForm.value.achieveTime);
  formData.append("description", infoForm.value.description);
  // 添加文件
  for (let file of infoForm.value.fileList) {
    formData.append('files', file);
  }
  try {
    // 添加文字信息
    const res = await importAchievement(formData);
    console.log(res)
    const {code, msg} = res.data;
    if (code != SUCCESS) {
      throw new Error(msg);
    }
    ElMessage.success(msg || "上传成果成功");
  } catch (e) {
    ElMessage.error(e?.message || "上传成果异常");
  }
}
const router = useRouter();
// 提交表单
const submitForm = async (formEl) => {
  if (!formEl) return
  await formEl.validate(async (valid, fields) => {
    if (valid) {
      // 文件不能为空
      if(infoForm.value.fileList.length === 0) {
        ElMessage.error("请上传文件")
        return;
      }
      await addAchievement();
      router.back();
    } else {
      ElMessage.error("请保证信息填写正确");
    }
  })
}

</script>
<template>
  <div class="input-page">
    <div class="input-container">
      <div class="page-header">
        <el-page-header @back="$router.back()" title="返回">
          <template #content>
            <span>上传页面</span>
          </template>
        </el-page-header>
      </div>
      <div class="file-panel">
        <div class="panel-header">
          <h3 class="title">实践成果上传</h3>
          <div class="tip">请上传您获得的实践成果的重要信息：<em>封面 / 目录 / 封底 / 奖状 / 权利要求书 / 申报书</em>等
          </div>
        </div>
        <el-divider/>
        <div class="panel-bd">
          <el-upload
              drag
              multiple
              ref="uploaderRef"
              :file-list="infoForm.fileList"
              :limit="FileLimitNum"
              :http-request="httpRequest"
              :on-exceed="handleExceed"
              :before-upload="handleBeforeUpload"
              :before-remove="handleBeforeRemove"
              :on-remove="handleRemove"
          >
            <el-icon class="el-icon--upload" color="#409eff">
              <upload-filled/>
            </el-icon>
            <div class="el-upload__text">
              点击或将文件拖拽到这里上传
            </div>
            <template #tip>
              <div class="el-upload__tip">
                类型支持 .PDF .JPG .PNG
              </div>
            </template>
          </el-upload>
        </div>
      </div>
      <div class="info-panel">
        <div class="panel-header">
          <h3 class="title">填写信息</h3>
          <el-divider direction="vertical"/>
          <div class="fast-input-link">
            <span class="text" @click="openFastInputDlg">智能信息填写</span>
            <span class="tip">带<em>*</em>为必填项</span>
          </div>
        </div>
        <el-divider/>
        <div class="panel-bd">
          <el-form
              label-width="150px"
              label-position="left"
              :model="infoForm"
              :rules="rules"
              ref="infoFormRef"
          >
            <el-form-item label="实践成果名称" prop="title">
              <el-input v-model="infoForm.title" clearable/>
            </el-form-item>
            <div class="form-item-card">
              <div class="card-header">
                <el-form-item label="持有者" prop="possessors">
                  <div
                      @click="addPossessor"
                      class="add-item-btn"
                  >
                    <el-icon color="#409eff" :size="20">
                      <CirclePlus/>
                    </el-icon>
                  </div>
                </el-form-item>
              </div>
              <div class="card-body">
                <el-card shadow="never">
                  <el-row
                      v-for="(possessor,idx) in infoForm.possessors"
                      :key="idx"
                  >
                    <el-col :span="8">
                      <!--                      Cake prop定位传值，rules定义规则 -->
                      <el-form-item
                          label="学号（工号）"
                          label-width="120px"
                          :prop="`possessors[${idx}].id`"
                          :rules="rules.possessorId"
                      >
                        <el-input v-model="possessor.id"
                                  @input="possessor.queryHandler(possessor, possessor.id)"/>
                      </el-form-item>
                    </el-col>
                    <el-col :offset="1" :span="5">
                      <el-form-item
                          label="姓名"
                          label-width="60px"
                          :prop="`possessors[${idx}].name`"
                          :rules="rules.username"
                      >
                        <el-input v-model="possessor.name"/>
                      </el-form-item>
                    </el-col>
                    <el-col :offset="1" :span="2" v-show="infoForm.possessors.length !== 1">
                      <div
                          style="marginTop: 6px;cursor: pointer;"
                          @click="removePossessor(idx)"
                      >
                        <el-icon color="#409eff" :size="20">
                          <RemoveFilled/>
                        </el-icon>
                      </div>
                    </el-col>
                  </el-row>
                </el-card>
              </div>
            </div>
            <div class="form-item-card">
              <div class="card-header">
                <el-form-item label="指导老师">
                  <el-radio :label="1" v-model="infoForm.advisor.have">有</el-radio>
                  <el-radio :label="0" v-model="infoForm.advisor.have">无</el-radio>
                  <div
                      @click="addAdvisor"
                      class="add-item-btn"
                      v-show="infoForm.advisor.have"
                  >
                    <el-icon color="#409eff" :size="20">
                      <CirclePlus/>
                    </el-icon>
                  </div>
                </el-form-item>
              </div>
              <div class="card-body" v-show="infoForm.advisor.have">
                <el-card shadow="never">
                  <el-row
                      v-for="(info,idx) in infoForm.advisor.infos"
                      :key="idx"
                  >
                    <el-col :span="8">
                      <el-form-item
                          label="工号"
                          label-width="120px"
                          :prop="`advisor.infos[${idx}].id`"
                          :rules="rules.advisorId"
                      >
                        <el-input v-model="info.id" @input="info.queryHandler(info, info.id)"/>
                      </el-form-item>
                    </el-col>
                    <el-col :offset="1" :span="5">
                      <el-form-item
                          label="姓名"
                          label-width="60px"
                          :prop="`advisor.infos[${idx}].name`"
                          :rules="rules.username"
                      >
                        <el-input v-model="info.name"/>
                      </el-form-item>
                    </el-col>
                    <el-col :offset="1" :span="2" v-show="infoForm.advisor.infos.length !== 1">
                      <div
                          style="marginTop: 6px;cursor: pointer;"
                          @click="removeAdvisor(idx)"
                      >
                        <el-icon color="#409eff" :size="20">
                          <RemoveFilled/>
                        </el-icon>
                      </div>
                    </el-col>
                  </el-row>
                </el-card>
              </div>
            </div>
            <el-form-item label="所属类型" prop="type">
              <el-radio
                  v-for="(typeName, idx) in typeNameList"
                  :key="idx"
                  :label="idx"
                  v-model="infoForm.type"
              >
                {{ typeName }}
              </el-radio>
            </el-form-item>
            <el-form-item label="实践成果等级" prop="level">
              <el-select v-model="infoForm.level" placeholder="请选择">
                <el-option
                    v-for="(level, idx) in levelList"
                    :key="idx"
                    :label="level"
                    :value="level"
                />
              </el-select>
            </el-form-item>
            <el-form-item label="获取时间" prop="achieveTime">
              <el-input placeholder="如：2022-05-20" v-model="infoForm.achieveTime"/>
            </el-form-item>
            <el-form-item label="实践成果简介" prop="description">
              <el-input type="textarea" :rows="5" v-model="infoForm.description"/>
            </el-form-item>
          </el-form>
        </div>
      </div>
      <el-row justify="center">
        <el-button type="primary" style="width:150px;" @click="submitForm(infoFormRef)">上传</el-button>
      </el-row>
    </div>
    <el-dialog
        v-model="showFastInputDlg"
        :show-close="true"
        class="fast-input-dialog"
    >
      <template #header="{ close, titleId, titleClass }">
        <div class="header">
          <span :id="titleId" :class="titleClass">智能信息填写</span>
          <span class="tip">系统将自动识别实践成果名称、持有者、指导老师等信息并填充到表格对应项</span>
        </div>
      </template>
      <div class="content">
        <div class="example">
          <div class="label">「实践成果信息格式」：</div>
          <div class="text">
            <p class="format">实践成果名称.持有者1学号(工号),持有者2学号(工号).指导老师1工号,指导老师2工号.年-月-日</p>
            <p class="case">例：柑橘仿生采摘机器人.20202571xxxx,20212571xxxx.30004327.2022-05-20</p>
            <p class="note">注：不同项之间用"."连接，同项用","分隔，相邻无空格，所有标点符号请用英文半角符号。</p>
          </div>
        </div>
        <div class="input-box">
          <el-input
              v-model="fastInputText"
              type="textarea"
              :rows="4"
              placeholder="请留意您粘贴的信息是否正确（如有多条，仅读取第一条成果）。"
          ></el-input>
        </div>
        <el-row justify="end">
          <el-button type="primary" @click="handleFastInput">智能填写</el-button>
        </el-row>
      </div>
    </el-dialog>
  </div>
</template>

<style lang="less" scoped>
.page-header {
  padding: 10px 5px;
}
em.required {
  margin: 0 2px;
  font-style: normal;
  color: red;
}

.form-item-card {
  margin-bottom: 18px;

  .add-item-btn {
    display: flex;
    align-items: center;
    cursor: pointer;
  }
}

.input-page {
  overflow: hidden;
  background: #f7f7f7;
}

.input-container {
  width: 1200px;
  margin: 40px auto;

  .info-panel,
  .file-panel {
    padding: 15px 25px;
    background: #fff;
    margin-bottom: 25px;
  }

  .el-button {
    width: 100px;
  }
}

.panel-header {
  display: flex;
  align-items: center;
}

.info-panel {
  .panel-header .fast-input-link {
    .text {
      font-size: 18px;
      color: #409eff;
      cursor: pointer;
    }

    .tip {
      margin-left: 8px;
      font-size: 12px;
      color: #7F7F7F;

      em {
        margin: 0 2px;
        font-style: normal;
        color: red;
      }
    }
  }
}

.file-panel {
  .panel-header .tip {
    align-self: end;
    margin-left: 8px;
    font-size: 12px;

    em {
      font-weight: 700;
      font-style: normal;
    }
  }
}

.fast-input-dialog {
  .header .tip {
    margin-left: 6px;
    font-size: 12px;
    color: #7f7f7f;
  }

  .content {
    .example {
      display: flex;
      padding-bottom: 20px;
      font-size: 12px;
      color: #7F7F7F;

      .label {
        width: 140px;
      }

      .text {
        width: 0;
        flex: auto;
      }
    }
  }

  .input-box {
    margin-bottom: 20px;
  }
}
</style>
